<template>
  <div>
    <van-nav-bar :title="chatUid" left-text="返回" left-arrow fixed safe-area-inset-top placeholder @click-left="toHomePage"/>
    <div class="chat-wrap" id="chatRef">
      <div class="msg-wrap" v-for="(item, index) in getChatList(chatUid)" :key="index">
        <div class="msg-right" v-if="item.fromUid == getLoginUid()">
          <div class="msg-right-box">
            <div class="msg-right-title">
              <span class="text">{{ item.fromUid }}</span>
            </div>
            <div class="msg-right-content">
              {{ item.msg }}
            </div>
            <div class="msg-right-bottom">
              <span>{{ item.date }}</span>
            </div>
          </div>
          <div class="msg-right-img">
            <van-image
              radius="5"
              width="46"
              height="46"
              src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
            />
          </div>
        </div>
        <div class="msg-left" v-else>
          <div class="msg-left-img">
            <van-image
              radius="5"
              width="46"
              height="46"
              src="https://fastly.jsdelivr.net/npm/@vant/assets/cat.jpeg"
            />
          </div>
          <div class="msg-left-box">
            <div class="msg-left-title">
              <span>{{ item.fromUid }}</span>
            </div>
            <div class="msg-left-content">
              {{ item.msg }}
            </div>
            <div class="msg-left-bottom">
              <span>{{ item.date }}</span>
            </div>
          </div>
        </div>
      </div>
    </div>
    <div class="chat-tool-wrap">
      <div class="box-left">
        <van-cell-group inset>
          <van-field
            v-model="message"
            rows="1"
            autosize
            type="textarea"
            maxlength="100"
            placeholder="请输入消息"
          />
        </van-cell-group>
      </div>
      <div class="box-right">
        <van-button icon="plus" round plain type="primary" size="small" @click="show = true"/>
        <van-button type="primary" style="margin-left: 10px;" plain size="small" @click="sendMsg">发送</van-button>
      </div>
    </div>

    <van-action-sheet v-model:show="show" :actions="actions" cancel-text="取消" @select="onSelect" close-on-click-action/>

    <van-dialog v-model:show="showVideo" 
      showConfirmButton 
      confirm-button-color="#e2155b"
      confirmButtonText="挂断" 
      @confirm="handleVideoClose">
      <video height="300px" ref="videoDOM" autoplay playsinline muted></video>
    </van-dialog>
  </div>
</template>

<script setup>
import "webrtc-adapter"
import { onMounted, onUnmounted, ref, nextTick, watch } from 'vue'
import { useRouter, useRoute } from 'vue-router'
import { format } from 'date-fns'
import { showFailToast } from 'vant'
import { storeToRefs } from 'pinia'
import { tabStore, videoStore } from '@/stores/mqttStore'
import { publish, addChat, clearChatNum, getChatList, getLoginUid } from '@/util/clientUtil'


const router = useRouter()
const route = useRoute()
const { targetChatUid } = storeToRefs(tabStore())
const { videoRefuse, videoOk, videoAnswer, videoToCandidate } = storeToRefs(videoStore())
const chatUid = route.query.uid

const message = ref(null)
const show = ref(false)
const actions = [
  { 
    name: '屏幕共享',
    key: 'video'
  },
  { 
    name: '语音通话',
    key: 'voice'
  },
];
const showVideo = ref(false)
const videoDOM = ref()
let localStream = null
let pc = null

onMounted(() => {
  scrollToBottom()
  clearChatNum(chatUid)
  targetChatUid.value = chatUid
})

onUnmounted(() => {
  targetChatUid.value = null
  if(showVideo.value){
    handleVideoClose()
  }
})

const onSelect = (item) => {
  if(item.key === 'video'){
    handleVideo()
  }
  if(item.key === 'voice'){
    handleVoice()
  }
};

const toHomePage = () => {
  router.push({
    path: '/'
  })
}

const formatDate = (date) => {
  return format(date, "yyyy-MM-dd HH:mm:ss")
}

const sendMsg = () => {
  if(!message.value){
    showFailToast('消息不能为空');
    return
  }

  const data = {
    fromUid: getLoginUid(),
    toUid: chatUid,
    msg: message.value,
    type: 'chat-msg',
    date: formatDate(new Date())
  }

  publish(chatUid, JSON.stringify(data))
  addChat(chatUid, data)
  message.value = null
}

const handleChatVideo = (data, key) => {
  const param = {
    fromUid: getLoginUid(),
    toUid: chatUid,
    data: data,
    key: key,
    type: 'chat-video',
    date: formatDate(new Date())
  }
  publish(chatUid, JSON.stringify(param))
}

const scrollToBottom = () =>{
  const box = document.getElementById('chatRef');
  if(!box){
    return
  }
  nextTick(() => {
    box.scrollTop = box.scrollHeight
  })
}

const getPeer = () => {
  if(!pc){
    pc = new RTCPeerConnection({
      iceServers: [
        { 
          urls: 'stun:120.78.64.113'
        },
        {
          urls: "turn:120.78.64.113:3478",
          username: "kurento",
          credential: "kurento",
        },
      ],
    })
  }
  return pc
}

const handleOffer = () => {
  const rtcPeer = getPeer()
  rtcPeer.onicecandidate = event => {
    if (event.candidate) {
      handleChatVideo(event.candidate, 'invite-from-candidate')
    }
  }

  localStream.getTracks().forEach(track => rtcPeer.addTrack(track, localStream))

  rtcPeer.createOffer().then(offer => {
    rtcPeer.setLocalDescription(offer)
    handleChatVideo(offer, 'invite-offer')
  }).catch(error => {
    console.log('handleOffer error:', error)
  })
}

const handleAnswer = () => {
  pc.setRemoteDescription(videoAnswer.value)
  .catch(error => {
    console.log('handleAnswer error:', error)
  })
}

const handleCandidate = () => {
  pc.addIceCandidate(new RTCIceCandidate(videoToCandidate.value))
  .catch(error => {
    console.log('to handleCandidate error:', error)
  })
}

const handleVideo = () => {
  showVideo.value = true
  navigator.mediaDevices.getDisplayMedia(
    {
      audio: false,
      video: true
    }
  ).then(stream => {
    localStream = stream
    videoDOM.value.srcObject = stream
    videoDOM.value.play()
    handleChatVideo(null, 'invite')
  }).catch(error => {
    console.log('handleVideo error:', error)
  })
}

const handleVideoClose = () => {
  try{
    if(localStream){
      localStream.getTracks().forEach(track => track.stop())
    }
  }catch(error){
    console.log('handleVideoClose error:', error)
  }finally{
    handleChatVideo(null, 'invite-end')
  }
}

const handleVoice = () => {

}

watch(getChatList(chatUid), (newValue) => {
  scrollToBottom()
})

watch(videoRefuse, (newValue) => {
  handleVideoClose()
  showVideo.value = false
})

watch(videoOk, (newValue) => {
  handleOffer()
})

watch(videoAnswer, (newValue) => {
  handleAnswer()
})

watch(videoToCandidate, (newValue) => {
  handleCandidate()
})
</script>

<style lang="less" scoped>
.chat-wrap{
  width: 100vw;
  max-height: calc(100vh - 132px);
  overflow: auto;
  padding-top: 10px;
  padding-bottom: 10px;

  .msg-wrap{
    min-height: 56px;
    padding: 10px;
    margin-bottom: 10px;

    .msg-right{
      display: flex;
      justify-content: flex-end;

      .msg-right-box{
        max-width: 250px;

        .msg-right-title{
          text-align: right;
          margin-bottom: 3px;
          color: #909399;
          font-size: 14px;
        }

        .msg-right-content{
          border-radius: 5px;
          padding: 10px;
          background-color: #ffffff;
          margin-bottom: 3px;
        }

        .msg-right-bottom{
          font-size: 12px;
          color: #C0C4CC;
        }
      }

      .msg-right-img{
        margin-left: 10px;
        height: 46px;
        width: 46px;
        border-radius: 5px;
        background-color: brown;
      }
    }

    .msg-left{
      display: flex;
      justify-content: flex-start;

      .msg-left-img{
        height: 46px;
        width: 46px;
        border-radius: 5px; 
        background-color: brown;
        margin-right: 10px;
      }

      .msg-left-box{
        max-width: 250px;

        .msg-left-title{
          text-align: left;
          margin-bottom: 3px;
          color: #909399;
          font-size: 14px;
        }

        .msg-left-content{
          border-radius: 5px;
          padding: 10px;
          background-color: #ffffff;
          margin-bottom: 3px;
        }

        .msg-left-bottom{
          text-align: right;
          font-size: 12px;
          color: #C0C4CC;
        }
      }
    }
  }
}

.chat-tool-wrap{
  width: 100vw;
  min-height: 54px;
  max-height: 174px;
  position: absolute;
  padding-top: 5px;
  padding-bottom: 5px;
  background-color: #edeff6;
  bottom: 0;
  display: flex;
  flex-wrap: nowrap;
  align-items: center;
  overflow: auto;

  .box-left{
    width: 75%;
  }
}

.wrapper{
  width: 390px;
  height: 844px;
}
</style>